package com.jack.lib.base

import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.content.res.Resources
import android.os.Bundle
import android.util.TypedValue
import android.view.MotionEvent
import android.view.View
import android.widget.EditText
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintSet
import androidx.core.view.updatePadding
import androidx.lifecycle.Lifecycle
import androidx.viewbinding.ViewBinding
import com.blankj.utilcode.util.KeyboardUtils
import com.blankj.utilcode.util.ReflectUtils
import com.gyf.immersionbar.ktx.immersionBar
import com.jack.lib.base.databinding.ActivityBaseBinding
import com.jack.lib.base.databinding.LayoutHeaderBinding
import com.jack.lib.base.header.HeaderConfigurator
import com.jack.lib.base.header.IconType
import com.jack.lib.core.ext.*
import com.jack.lib.core.net.JBaseData
import com.jack.lib.core.net.JNetView
import com.jack.lib.core.ui.JWindow
import com.jack.lib.core.utils.AndroidBug5497Workaround
import com.jack.lib.core.utils.AppManager

/**
 * 作者: jack(黄冲)
 * 邮箱: 907755845@qq.com
 * create on 2017/6/17
 */
abstract class BaseActivity<VB: ViewBinding> : SwipeBackActivity(), JNetView, IActivityCallback {

    protected lateinit var mainBinding: ActivityBaseBinding
    protected lateinit var headerBinding: LayoutHeaderBinding
    protected val headerConfigurator by lazy { HeaderConfigurator() }
    protected lateinit var binding: VB
    private val attributesCallbacks by lazy { arrayListOf<IAttributesCallback>() }
    private var attributesInterceptor: IAttributesInterceptor = object: IAttributesInterceptor { }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        AppManager.getInstance().addActivity(this)
        initToolbarColor()
        loadView()
        onCreateView(savedInstanceState)
        initSoftKeyboardSetting()
    }

    override fun attachBaseContext(newBase: Context) {
        val attachBaseContext = attributesInterceptor.attachBaseContext(newBase)
        super.attachBaseContext(attachBaseContext)
        for (attributesCallback in attributesCallbacks) {
            attributesCallback.attachBaseContext(attachBaseContext)
        }
    }

    protected open fun initSoftKeyboardSetting() {
        AndroidBug5497Workaround.assistActivity(this)
    }

    protected open fun initToolbarColor() {
        immersionBar {
            statusBarDarkFont(true)
        }
    }

    private fun loadView() {

        mainBinding = ActivityBaseBinding.inflate(layoutInflater)
        headerBinding = mainBinding.layoutHeader
        setContentView(mainBinding.root)

        initHeader(headerConfigurator)
        loadHeader()

        mainBinding.mainEventLinearLayout.setOnTouchEvent { mainTouchEvent(it) }
        mainBinding.mainEventLinearLayout.setOnDownListener { mainDownEvent(it) }

        //setSwipeBackEnable(AppManager.getInstance().allActivity.size > 1)
        setSwipeBackEnable(false)

        binding = ReflectUtils.reflect(arguments(0)).method("inflate", layoutInflater, mainBinding.layoutChild, true).get()
    }

    private fun loadHeader() {
        headerBinding.root.setBackgroundColor(headerConfigurator.backgroundColor)
        headerBinding.root.elevation = headerConfigurator.elevation.toFloat()
        headerBinding.root.layoutParams.width = headerConfigurator.width
        headerBinding.root.layoutParams.height = headerConfigurator.height
        headerBinding.root.updatePadding(top = headerConfigurator.paddingTop)

        if (headerConfigurator.immersed) {
            ConstraintSet().apply {
                clone(mainBinding.root)
                connect(mainBinding.layoutMain.id, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP)
            }.applyTo(mainBinding.root)
        }

        var iconView: TextView
        headerConfigurator.icons.forEach {
            iconView = when (it.type) {
                IconType.BACK -> headerBinding.back
                IconType.TITLE -> headerBinding.title
                IconType.TITLE_LEFT -> headerBinding.titleLeft
                IconType.RIGHT -> headerBinding.right
                IconType.RIGHT_SECOND -> headerBinding.rightSecond
            }
            iconView.background = it.drawable
            iconView.text = it.text
            iconView.setTextSize(TypedValue.COMPLEX_UNIT_PX, it.textSize.toFloat())
            iconView.setTextColor(it.textColor)
            iconView.typeface = it.typeface
            iconView.expand(it.clickExpand, it.clickExpand)
            iconView.layoutParams.width = it.width
            iconView.layoutParams.height = it.height
            it.click?.apply { iconView.setOnClickListener { this.invoke() } }
        }
    }

    /**
     * time    : 2019/2/20 9:48
     * desc    : 隐藏头部
     * versions: 1.0
     */
    protected fun hideHeader() {
        mainBinding.layoutHeader.root.gone()
    }

    /**
     * time    : 2019/2/20 9:48
     * desc    : 显示头部
     * versions: 1.0
     */
    protected fun showHeader() {
        mainBinding.layoutHeader.root.visible()
    }

    protected fun setErrorView(binding: ViewBinding) {
        mainBinding.layoutError.addView(binding.root)
        mainBinding.layoutChild.invisible()
    }

    protected fun setChildInterceptEvent(intercept: Boolean) {
        mainBinding.layoutChild.setInterceptEvent(intercept)
    }


    fun hideError() {
        mainBinding.layoutError.gone()
        mainBinding.layoutChild.visible()
    }

    fun showError() {
        mainBinding.layoutError.visible()
        mainBinding.layoutChild.invisible()
    }

    override fun onDestroy() {
        super.onDestroy()
        AppManager.getInstance().removeActivity(this)
    }

    protected abstract fun onCreateView(savedInstanceState: Bundle?)
    protected abstract fun initHeader(config: HeaderConfigurator)

    override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
        if (isOutsideCloseKeyboard() && ev.action == MotionEvent.ACTION_DOWN && isShouldHideKeyboard(currentFocus, ev)) {
            KeyboardUtils.hideSoftInput(this)
        }
        return super.dispatchTouchEvent(ev)
    }

    private fun isShouldHideKeyboard(v: View?, event: MotionEvent): Boolean {
        return v is EditText && !v.pointInView(event.rawX, event.rawY)
    }

    open fun isOutsideCloseKeyboard() = true

    open fun mainTouchEvent(event: MotionEvent?) {}

    open fun mainDownEvent(event: MotionEvent?) {}


    override fun onFill(bean: JBaseData<*>) {
        toastW(bean.message())
    }

    override fun onError(cause: Throwable) {
        toastW(cause.message)
    }

    override fun showLoading() {
        JWindow.showLoading(this)
    }

    override fun hideLoading() {
        JWindow.hideLoading()
    }

    override fun lifecycle(): Lifecycle = lifecycle

    override fun onSaveInstanceState(outState: Bundle) {
        val onSaveInstanceState = attributesInterceptor.onSaveInstanceState(outState)
        super.onSaveInstanceState(onSaveInstanceState)
        for (attributesCallback in attributesCallbacks) {
            attributesCallback.onSaveInstanceState(onSaveInstanceState)
        }
    }

    override fun onRestoreInstanceState(savedInstanceState: Bundle) {
        val onRestoreInstanceState = attributesInterceptor.onRestoreInstanceState(savedInstanceState)
        super.onRestoreInstanceState(onRestoreInstanceState)
        for (attributesCallback in attributesCallbacks) {
            attributesCallback.onRestoreInstanceState(onRestoreInstanceState)
        }
    }

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        for (attributesCallback in attributesCallbacks) {
            attributesCallback.onAttachedToWindow()
        }
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        for (attributesCallback in attributesCallbacks) {
            attributesCallback.onDetachedFromWindow()
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        for (attributesCallback in attributesCallbacks) {
            attributesCallback.onActivityResult(requestCode, resultCode, data)
        }
    }

    override fun getResources(): Resources {
        val resources = attributesInterceptor.getResources(super.getResources())
        for (attributesCallback in attributesCallbacks) {
            attributesCallback.getResources(resources)
        }
        return resources
    }

    override fun onConfigurationChanged(newConfig: Configuration) {
        val onConfigurationChanged = attributesInterceptor.onConfigurationChanged(newConfig)
        super.onConfigurationChanged(onConfigurationChanged)
        for (attributesCallback in attributesCallbacks) {
            attributesCallback.onConfigurationChanged(onConfigurationChanged)
        }
    }

    override fun registerAttributesCallback(callback: IAttributesCallback) {
        if (!attributesCallbacks.contains(callback)) {
            attributesCallbacks.add(callback)
        }
    }

    override fun unregisterAttributesCallback(callback: IAttributesCallback) {
        attributesCallbacks.remove(callback)
    }

    override fun setAttributesInterceptor(interceptor: IAttributesInterceptor) {
        attributesInterceptor = interceptor
    }
}